﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace System.Windows
{
    /// <summary>
    /// Implements a helper class for common <see cref="System.Windows.Media.Animation.Storyboard"/> objects.
    /// </summary>
    public class Animation
    {
        private static int  _StoryboardId = 1;

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.Storyboard"/> instance.
        /// </summary>
        /// <param name="duration">The duration of the storyboard</param>
        /// <returns>A new <see cref="System.Windows.Media.Animation.Storyboard"/> instance</returns>
        public static Storyboard CreateStoryboard(TimeSpan duration)
        {
            return CreateStoryboard(duration, new RepeatBehavior(1.0), false);
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.Storyboard"/> instance.
        /// </summary>
        /// <param name="duration">The duration of the storyboard</param>
        /// <param name="repeatCount">The repeat count of the storyboard</param>
        /// <returns>A new <see cref="System.Windows.Media.Animation.Storyboard"/> instance</returns>
        public static Storyboard CreateStoryboard(TimeSpan duration, double repeatCount)
        {
            return CreateStoryboard(duration, new RepeatBehavior(repeatCount), false);
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.Storyboard"/> instance.
        /// </summary>
        /// <param name="duration">The duration of the storyboard</param>
        /// <param name="repeat">The <see cref="System.Windows.Media.Animation.RepeatBehavior"/> of the storyboard</param>
        /// <returns>A new <see cref="System.Windows.Media.Animation.Storyboard"/> instance</returns>
        public static Storyboard CreateStoryboard(TimeSpan duration, RepeatBehavior repeat)
        {
            return CreateStoryboard(duration, repeat, false);
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.Storyboard"/> instance.
        /// </summary>
        /// <param name="duration">The duration of the storyboard</param>
        /// <param name="repeat">The <see cref="System.Windows.Media.Animation.RepeatBehavior"/> of the storyboard</param>
        /// <param name="autoReverse">A boolean value indicating whether the storyboard should auto-reverse on completion</param>
        /// <returns>A new <see cref="System.Windows.Media.Animation.Storyboard"/> instance</returns>
        public static Storyboard CreateStoryboard(TimeSpan duration, RepeatBehavior repeat, bool autoReverse)
        {
            Storyboard storyboard = new Storyboard();
            storyboard.Duration = new Duration(duration);
            storyboard.RepeatBehavior = repeat;
            storyboard.AutoReverse = autoReverse;
            storyboard.SetValue(FrameworkElement.NameProperty, String.Format("Storyboard{0}", _StoryboardId++));

            return storyboard;
        }

        /// <summary>
        /// Sets the the target element for a timeline object
        /// </summary>
        /// <param name="timeline">The timeline instance</param>
        /// <param name="target">The target for the timeline</param>
        /// <param name="propertyName">The target property name for the timeline</param>
        public static void SetTarget(Timeline timeline, DependencyObject target, string propertyName)
        {
            Storyboard.SetTarget(timeline, target);
            Storyboard.SetTargetProperty(timeline, new PropertyPath(propertyName));
        }

        /// <summary>
        /// Sets the the target element for a timeline object by name
        /// </summary>
        /// <param name="timeline">The timeline instance</param>
        /// <param name="targetName">The target name of the Dependency object for the target</param>
        /// <param name="propertyName">The target property name for the timeline</param>
        public static void SetTargetName(Timeline timeline, string targetName, string propertyName)
        {
            Storyboard.SetTargetName(timeline, targetName);
            Storyboard.SetTargetProperty(timeline, new PropertyPath(propertyName));
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames"/> instance.
        /// </summary>
        /// <remarks>
        /// NOTE: This method does NOT append the timeline to the Storyboard children.
        /// </remarks>
        /// <param name="storyboard">The storyboard to which</param>
        /// <param name="target">The target object whnich the timeline will animate</param>
        /// <param name="propertyName">The target property which the timeline will animate</param>
        /// <returns>A new <see cref="System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames"/> instance.</returns>
        public static DoubleAnimationUsingKeyFrames CreateKeyFrameAnimation(Storyboard storyboard, DependencyObject target, string propertyName)
        {
            DoubleAnimationUsingKeyFrames anim = new DoubleAnimationUsingKeyFrames();
            anim.Duration = storyboard.Duration;
            SetTarget(anim, target, propertyName);
            return anim;
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.DoubleAnimation"/> instance.
        /// </summary>
        /// <remarks>
        /// NOTE: This method does NOT append the timeline to the Storyboard children.
        /// </remarks>
        /// <param name="storyboard">The storyboard to which</param>
        /// <param name="target">The target object whnich the timeline will animate</param>
        /// <param name="propertyName">The target property which the timeline will animate</param>
        /// <param name="from">The starting double value for the timeline</param>
        /// <param name="to">The ending double value for the timeline</param>
        /// <returns>A new <see cref="System.Windows.Media.Animation.DoubleAnimation"/> instance.</returns>
        public static DoubleAnimation CreateAnimation(Storyboard storyboard, DependencyObject target, string propertyName, double from, double to)
        {
            DoubleAnimation anim = new DoubleAnimation();
            anim.Duration = storyboard.Duration;
            anim.From = from;
            anim.To = to;
            SetTarget(anim, target, propertyName);

            return anim;
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.SplineDoubleKeyFrame"/> instance.
        /// </summary>
        /// <param name="seconds">The position is seconds of the key frame</param>
        /// <param name="value">The value for the key frame</param>
        /// <param name="control1">The first control point for the spline key frame</param>
        /// <param name="control2">The second control point for the spline key frame</param>
        /// <returns>A <see cref="System.Windows.Media.Animation.SplineDoubleKeyFrame"/> instance.</returns>
        public static SplineDoubleKeyFrame CreateSplineKeyFrame(double seconds, double value, Point control1, Point control2)
        {
            SplineDoubleKeyFrame frame = new SplineDoubleKeyFrame();
            frame.KeySpline = new KeySpline();
            frame.KeySpline.ControlPoint1 = control1;
            frame.KeySpline.ControlPoint2 = control2;
            frame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(seconds));
            frame.Value = value;

            return frame;
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.DiscreteDoubleKeyFrame"/> instance.
        /// </summary>
        /// <param name="seconds">The seconds for the key frame</param>
        /// <param name="value">The value for the key frame</param>
        /// <returns>A <see cref="System.Windows.Media.Animation.DiscreteDoubleKeyFrame"/> instance.</returns>
        public static DiscreteDoubleKeyFrame CreateDiscreteKeyFrame(double seconds, double value)
        {
            DiscreteDoubleKeyFrame frame = new DiscreteDoubleKeyFrame();
            frame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(seconds));
            frame.Value = value;

            return frame;
        }

        /// <summary>
        /// Creates a <see cref="System.Windows.Media.Animation.LinearDoubleKeyFrame"/> instance.
        /// </summary>
        /// <param name="seconds">The seconds for the key frame</param>
        /// <param name="value">The value for the key frame</param>
        /// <returns>A <see cref="System.Windows.Media.Animation.LinearDoubleKeyFrame"/> instance.</returns>
        public static LinearDoubleKeyFrame CreateLinearKeyFrame(double seconds, double value)
        {
            LinearDoubleKeyFrame frame = new LinearDoubleKeyFrame();
            frame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(seconds));
            frame.Value = value;

            return frame;
        }
    }
}
